package com.example.util;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import com.alibaba.fastjson.JSON;
import com.example.bean.Ftp;
import com.sun.xml.internal.ws.util.UtilException;

public class BeanUtils {
	
	/**
	 * 将sourceBean 中的非空字段，填充至targetBean，要求sourceBean 与 targetBean 的类型一致
	 * @author liuhuaqing
	 * @date   2018年6月5日
	 * @param targetBean
	 * @param sourceBean
	 */
	public static void fillNotNullFild(Object target,Object source)
	{
		 if (target.getClass() != source.getClass()) {
			
			throw new RuntimeException("类型不匹配");
		}
		 
		
		Class c=source.getClass();
		Field[] f=c.getDeclaredFields();
		
		
		
		Method[] methods=c.getDeclaredMethods(); //不包含继承方法
		
		HashMap<String,Object> get=new HashMap<String,Object>();
		HashSet<String> set=new HashSet<String>();
		for(int i=0;i<methods.length;i++)
		{
			
			Method m=methods[i];
			String names=m.getName();
			if(names.startsWith("get"))
			{
				String fild=names.substring(3);
				Object returnObject = null;
				try {
					returnObject = m.invoke(source,null );
				} catch (IllegalAccessException e) {
					
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					
					e.printStackTrace();
				}
				get.put(fild, returnObject);
			
			}else if(names.startsWith("set"))
			{
				String fild=names.substring(3);
				set.add(fild);
			}
			
		}
		
		Iterator<String> it=set.iterator();
		while(it.hasNext())
		{
			String filed=it.next();
			if(get.containsKey(filed))
			{
				Object o=get.get(filed);
				if(o==null)
				{
					continue;
				}
				
				Method m=null;
				try {
					m=c.getMethod("set"+filed, o.getClass());
				} catch (NoSuchMethodException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (SecurityException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				try {
					m.invoke(target, get.get(filed));
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
			
		}
	}
	
	
	
	
	
	/** 
	* 将Bean 使用map 内的值填充
	* @param bean
	* @param map void
	* @author liuhuaqing
	* @date 2018年6月14日下午1:37:19
	*/ 
	public static void fillObjectByMap(Object bean,Map<String,Object> map)
	{
		
		Class c=bean.getClass();
		Method[] methods=c.getMethods();
		for(int i=0;i<methods.length;i++)
		{
			Method m=methods[i];
			String name=m.getName();
			if(name.startsWith("set"))
			{
				String key=getFildNameBySetMethod(name,2);
				
				try {
					m.invoke(bean, map.get(key));
					
				} catch (Exception e) {
					
					e.printStackTrace();
					throw new RuntimeException("map 转换bean 失败:map 中字段类型"+map.get(key).getClass().getName());
				} 
			}
			
		}
		
		
	}
	
	
	
	/** 
	* 指定字段向 目标对象填充 值
	* @param target 目标对象
	* @param source 资源对象
	* @param filds 指定字段
	* @return
	* @throws RuntimeException T
	* @author liuhuaqing
	* @date 2018年8月17日上午9:32:43
	*/ 
	public static <T>T fillObjectByFilds(T target,T source,Set<String> filds) throws  UtilException
	{
		//通过加载类来判断是否一致
		if(target.getClass() !=  source.getClass())
		{
			return target;
		}
		
		for(String fild:filds)
		{
			
			Method getter=ReflectUtil.getGetterByFildName(fild, target.getClass());
			Method setter=ReflectUtil.getSetterByFildName(fild,  target.getClass());
			
			try {
				Object value=getter.invoke(source, null);
				setter.invoke(target, value);
			} catch (Exception e) {
				throw new UtilException("通过反射设置&获取值失败,key-"+fild+" target-"+JSON.toJSONString(target)+" source-"+JSON.toJSONString(source));
			} 
		}
		
		return target;
		
	}
	
	
	
	
	
	
	
	
	public static void main(String[] args) {
		/*Ftp f1=new Ftp();
		f1.setIpAddr("123123");
		f1.setPort(12);
		Ftp f2=new Ftp();
		f2.setPort(50);
		BeanUtils.fillNotNullFild(f2, f1);
		System.out.println(f2.getIpAddr());
		System.out.println(f2.getPort()+"");*/
		
		Ftp f1=new Ftp();
		Map<String,Object> map=new HashMap<>();
		map.put("ip_addr", "123123");
		map.put("port", 111);
		BeanUtils.fillObjectByMap(f1, map);
		
		System.out.println(f1.getIpAddr());
		System.out.println(f1.getPort()+"");
		
	}
	
	
	/** 
	* 通过bean 的set方法名称 获取 该字段 名称
	* @param methodName
	* @param mode 1 首字母小写,其他部分不改变模式    2(或其他)首字母小写，驼峰命名模式
	* @return String
	* @author liuhuaqing
	* @date 2018年6月14日下午1:46:31
	*/ 
	private static String getFildNameBySetMethod(String methodName,int mode)
	{
		
		
		String str=methodName.substring(3);
		if(mode==1)
		{
			return StringUtils.changeFirstChar(str, mode);
		}
		else
		{
			return StringUtils.getCamelStr(str);
		}
			
		
		
	}
}
